
<!DOCTYPE html>
<html>
<head>
    <title>揭棋</title>
    <link rel="shortcut icon" href="/static/imges/favicon.ico" type="image/x-icon">
    <style>
        canvas {cursor: pointer;}
        div {text-align: center;}
        button{margin-left: 50px;}
    </style>
</head>
<body>
<div>
    <button onclick="rs()">重新开始</button>
        <button onclick="j(1)">放大</button><button onclick="j(-1)">缩小</button>
    <label for="olu">可加入对局：</label><select id="olu"></select> <button onclick="initOLU()">刷新对局列表</button> <button id="sq" onclick="sq()">加入对局</button>
</div>
<div style="margin-top: 50px">
    <div style="position: absolute;float: right">
        <label for="mid">我的id：</label><span id="mid"></span><br>
        <label for="mid">对手id：</label><span id="eid"></span><br>
        <label for="mid">我是：</label><span id="me"></span>
        <div style="text-align: left">当前选中：<canvas id="sc"></canvas></div>
        <div style="text-align: left">当前回合：<span id="t"></span></div>
    </div>
    <div><canvas id="chessboard" style="border:1px solid red"></canvas></div>
</div>

<script>
    let sid,eid;let me=void 0;
    let ws =null;
    let w=null;
    let n=1;
    let c = {
        r:25,
        get d(){
            return 2*this.r;
        },
    };
    let rarr=[],barr=[];
    let g=null;
    const scan = document.getElementById("sc");
    const sctx = scan.getContext("2d");
    const canvas = document.getElementById('chessboard');
    const ctx = canvas.getContext('2d');
    let d;
    let fd ,yd={};

    function dr() {
        scan.width =c.d;scan.height = c.d;
        canvas.width = 9*c.d;
        canvas.height = 10*c.d;
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        dG();
        dCh();
        dSC();
    }
    function dSC() {
        document.getElementById("t").innerHTML = n===1?"红":"黑";

        sctx.clearRect(0, 0, scan.width, scan.height);
        if(g!==null){
            var o = d[g.x][g.y];
            sctx.beginPath();
            sctx.arc(c.r,c.r, c.r, 0, 2 * Math.PI, false);
            sctx.fillStyle = o.t?'red':'black';
            sctx.fill();
            sctx.lineWidth = 1/5*c.r;
            sctx.strokeStyle = '#003300';
            sctx.stroke();
            sctx.font = c.r+"px 楷体";
            sctx.fillStyle = 'white';
            sctx.fillText(o.n, 0.5*c.r, 1.25*c.r);
            sctx.restore();
        }
    }
    function cli(e) {
        if(me !==void 0 &&me!==n){
            return;
        }
        var {x,y}=zh(e);
        cli_do(x,y);
        wsmv(x,y);
    }
    function wsmv(x,y) {
        if(me !==void 0){
            var msg ={};
            msg.from = sid;
            msg.to = eid;
            msg.type = "5";
            msg.msg = JSON.stringify({"x":x,"y":y});
            ws.send(JSON.stringify(msg));
        }
    }
    function cli_do(x,y) {
        if(g==null && (d[x][y]===null || d[x][y].t !==n)){
            g=null;dSC();
            return;
        }
        if(g===null){
            g = {x,y};
        }else if(g!=null&&d[x][y]&&d[x][y].t===d[g.x][g.y].t){
            g={x,y};
        }else{
            mc(x,y);
        }
        dSC();dr();
    }
    function mc(x,y) {
        var o = {...d[g.x][g.y]};
        if(jy(o,x,y)){
            o.x=x;o.y=y;
            if(d[x]&&d[x][y]&&(d[x][y].n==="帅"||d[x][y].n==="将")){
                w = Math.abs(d[x][y].t-1);
            }
            d[x][y]=o;
            d[x][y].n=d[x][y].an;
            d[x][y].m=1;
            d[g.x][g.y]=null;
            g=null;
            n = 1-n;
            dr();
            if(w!=null){
                setTimeout(function () {
                    alert((w?"红":"黑")+"方胜利！")
                })
                canvas.removeEventListener("click",cli);
            }
        }
    }
    function jy(o,x,y) {
        if(d[x][y]!==null&&d[x][y].t===o.t){
            return false;
        }
        switch (o.n) {
            case "卒":case "兵":
                if(Math.abs(yd[o.t].x-o.x)>4){
                    return (Math.abs(yd[o.t].x-x)-Math.abs(yd[o.t].x-o.x)===1&&o.y===y) || ( o.x===x && Math.abs(o.y-y)===1 );
                }else{
                    return Math.abs(yd[o.t].x-x)-Math.abs(yd[o.t].x-o.x)===1&&o.y===y;
                }
            case "炮":
                if(!isl(o,x,y)){
                    return false;
                }
                let bu = bulb(o,x,y);
                return  ((!d[x][y]&&bu===0)||(d[x][y]&&bu===1));
            case "车":
                return isl(o,x,y)? bulb(o,x,y)===0:false;
            case "马":
                return Math.abs((x-o.x)*(y-o.y))===2 &&(  Math.abs(x-o.x)===2?!d[o.x+(x-o.x)/Math.abs(x-o.x)][o.y]:!d[o.x][o.y+(y-o.y)/Math.abs(y-o.y)] );
            case "相":case "象":
                return (o.m ===0? Math.abs(yd[o.t].x-x)<=4:true )&& Math.abs(x-o.x)===2&&Math.abs(y-o.y)===2 && !d[o.x+ (x-o.x)/Math.abs(x-o.x) ][o.y+(y-o.y)/Math.abs(y-o.y)];
            case "士":case "仕":
                return Math.abs(x-o.x)===1&&Math.abs(y-o.y)===1&& (o.m===0? ( Math.abs(yd[o.t].x-x)<=2 &&Math.abs(yd[o.t].y-y)<=1):true );
            case "将":case "帅":
                return (( (x===o.x&&y!==o.y)||(x!==o.x&&y===o.y) ) &&( Math.abs(yd[o.t].x-x)<=2 &&Math.abs(yd[o.t].y-y)<=1 )) || ( bulb(o,x,y)===0&& d[x]&&d[x][y]&&(d[x][y].n===(o.n==="将"?"帅":"将") ) );
            default:return false;
        }
    }
    function isl(o,x,y) {
        return (o.x===x&&o.y!==y)||(o.y===y&&o.x!==x);
    }
    function bulb(o,x,y) {
        let a=o.x+(o.x===x?0:(x-o.x)/Math.abs(x-o.x)),b=o.y+(o.y===y?0:(y-o.y)/Math.abs(y-o.y)),c=0;
        while (!(a===x&&b===y)){
            if(d[a]&&d[a][b]){
                c++;
            }
            a+= (o.x===x?0:(x-o.x)/Math.abs(x-o.x));
            b+= (o.y===y?0:(y-o.y)/Math.abs(y-o.y));
        }
        return c;
    }
    function zh(e) {
        return {y:Math.floor(e.offsetX/c.d),x:Math.floor(e.offsetY/c.d)};
    }
    function dc(p) {
        if(p==null){return;}
        ctx.beginPath();
        ctx.arc(p.y*c.d+c.r, p.x*c.d+c.r, c.r, 0, 2 * Math.PI, false);
        if(g!==null&&p.x===g.x&&p.y===g.y){
            ctx.fillStyle = 'green';
        }else{
            ctx.fillStyle = p.t?'red':'black';
        }
        ctx.fill();
        ctx.lineWidth = 1/5*c.r;
        ctx.strokeStyle = '#003300';
        ctx.stroke();
        if(p.m ===1){
            ctx.font = c.r+"px 楷体";
            ctx.fillStyle = 'white';
            ctx.fillText(p.n, p.y*c.d+0.5*c.r, p.x*c.d+1.25*c.r);
        }

        ctx.restore();
    }
    function dx(y,x){
        if(x!=0){
            ctx.moveTo(x*c.d+c.r -0.25*c.r ,y*c.d+c.r -0.25*c.r ); ctx.lineTo(x*c.d+c.r -0.25*c.r,y*c.d+c.r-0.25*c.r  -0.5*c.r );
            ctx.moveTo(x*c.d+c.r -0.25*c.r ,y*c.d+c.r -0.25*c.r +c.r ); ctx.lineTo(x*c.d+c.r -0.25*c.r,y*c.d+c.r-0.25*c.r  -0.5*c.r +c.r);
            ctx.moveTo(x*c.d+c.r -0.25*c.r ,y*c.d+c.r -0.25*c.r ); ctx.lineTo(x*c.d+c.r -0.25*c.r -0.5*c.r,y*c.d+c.r -0.25*c.r );
            ctx.moveTo(x*c.d+c.r -0.25*c.r ,y*c.d+c.r -0.25*c.r +0.5*c.r ); ctx.lineTo(x*c.d+c.r -0.25*c.r -0.5*c.r,y*c.d+c.r -0.25*c.r +0.5*c.r);
        }
        if(x!=8){
            ctx.moveTo(x*c.d+c.r +0.25*c.r ,y*c.d+c.r -0.25*c.r ); ctx.lineTo(x*c.d+c.r +0.25*c.r,y*c.d+c.r-0.25*c.r  -0.5*c.r );
            ctx.moveTo(x*c.d+c.r +0.25*c.r ,y*c.d+c.r -0.25*c.r +c.r ); ctx.lineTo(x*c.d+c.r +0.25*c.r,y*c.d+c.r-0.25*c.r  -0.5*c.r +c.r);
            ctx.moveTo(x*c.d+c.r -0.25*c.r +0.5*c.r,y*c.d+c.r -0.25*c.r ); ctx.lineTo(x*c.d+c.r -0.25*c.r +0.5*c.r+0.5*c.r,y*c.d+c.r -0.25*c.r);
            ctx.moveTo(x*c.d+c.r -0.25*c.r +0.5*c.r,y*c.d+c.r -0.25*c.r  +0.5*c.r); ctx.lineTo(x*c.d+c.r -0.25*c.r +0.5*c.r+0.5*c.r,y*c.d+c.r -0.25*c.r  +0.5*c.r);
        }
    }
    window.onload = function () {
        rs();
        initWs();
        initOLU();
    };
    function initOLU() {
        let olu = document.getElementById("olu");
        olu.innerHTML="";
        fetch("/chess/getJqOnlineUser").then(res=>{
            return res.json();
        }).then(res=>{
            res.data.forEach(o=>{
                if(sid!==o){
                    let opt = document.createElement("option");
                    opt.label=o;opt.value=o;
                    olu.append(opt);
                }
            })
        })
    }
    function initWs(){
        if ('WebSocket' in window) {
            wsc();
        } else {
            alert('当前浏览器不支持对战模式')
        }
    }
    function wsc() {
        try {
            ws = new WebSocket("wss://"+window.location.host+"/JWS");
        }catch (e) {
            ws = new WebSocket("ws://"+window.location.host+"/JWS");
        }

        ws.onerror = function () {
            console.log("系统消息： 连接异常")
        };

        ws.onopen = function (event) {
        }

        ws.onmessage = function (event) {
            msgHandle(JSON.parse(event.data));
        }
        ws.onclose = function () {
            console.log("系统消息： 连接关闭")
        }
        window.onbeforeunload = function () {
            ws.close();
        }
        function msgHandle(msg) {
            switch (msg.type) {
                case "0": sid=msg.msg;document.getElementById("mid").innerHTML =sid;
                    break;
                case "1":
                    let b = confirm("玩家"+msg.from+"申请加入对局是否接受？");
                    if(b){
                        msg.type = "2";
                        n=1;
                        me = n;
                        document.getElementById("sq").style.display="none";
                        eid = msg.from;
                        document.getElementById("eid").innerHTML = msg.from;
                        document.getElementById("me").innerHTML = me===1?"红":"黑";
                        re(msg);
                    }else{
                        msg.type = "3";
                    }
                    ws.send(JSON.stringify(msg));
                    break;
                case "2":
                    alert(msg.to+"接受你的对局");
                    me=1-n;
                    eid = msg.to;
                    document.getElementById("sq").style.display="none";
                    document.getElementById("eid").innerHTML = msg.to;
                    document.getElementById("me").innerHTML = me?"红":"黑";
                    break;
                case "3":
                    alert(msg.to+"拒绝你的对局"); document.getElementById("sq").style.display="";break;
                case "4":
                    alert(msg.from+"离开了对局");document.getElementById("sq").style.display="";break;
                case "5":
                    var mo = JSON.parse(msg.msg);
                    cli_do(mo.x,mo.y);
                    break;
                case "6":
                    rs(msg);
                    break;
                default:break;
            }
        }
    }
    function re(ms) {
        rs();
        var msg = {};
        msg.type = "6";
        msg.from = sid;
        msg.to = ms.from;

        var dt = {};
        dt.d = d;
        dt.me = me;
        dt.n = n;
        msg.msg = JSON.stringify(dt);
        ws.send(JSON.stringify(msg));

    }
    function rs(msg) {
        if(!msg){
            n=1;g=null;
            rarr=[];barr=[];
            d = new Array(10).fill(null).map(() => new Array(9).fill(null));yd={};
            w=null;
            initD();
            dr();
        }else{
            let p = JSON.parse(msg.msg);
            n= p.n;g=null;d=p.d;w=null;
            me = 1-p.me;
            dr();
        }
        canvas.addEventListener('click',cli)
    }
    function initD() {
        let ba = ["车","马","象","士","将","士","象","马","车"];
        let ra = ["车","马","相","仕","帅","仕","相","马","车"];
        for (var i=0;i<ba.length;i++){
            d[0][i] = new C(0,i,ra[i],1);
            d[9][i]= new C(9,i,ba[i],0);
            if(i!==4){
                rarr.push( d[0][i]);
                barr.push(d[9][i]);
            }
        }
        d[2][1] = new C(2,1,"炮",1);d[2][7] = new C(2,7,"炮",1); rarr.push(d[2][1]);rarr.push(d[2][7]);
        d[7][1] = new C(7,1,"炮",0);d[7][7] = new C(7,7,"炮",0);barr.push(d[7][1]);barr.push(d[7][7]);
        for(var i=0;i<10;i+=2){
            d[3][i] = new C(3,i,"兵",1);rarr.push(d[3][i]);
            d[6][i] = new C(6,i,"卒",0);barr.push(d[6][i]);
        }
        fd =dcp(d);
        yd[fd[0][4].t]=fd[0][4];
        yd[fd[9][4].t]=fd[9][4];
        let len = rarr.length;
        for(var i=0;i<len;i++){
            var red = rarr[i];
            let rnum = rdm(len);
            var redt= rarr[rnum];
            let ran = red.an; let ran1 = redt.an;
            red.an = ran1;redt.an=ran;

            var black = barr[i];
            let bnum = rdm(len);
            var blackt= barr[bnum];
            let ban = black.an; let ban1 = blackt.an;
            black.an = ban1;blackt.an=ban;
        }
        rarr.forEach(o=>{o.m=0});barr.forEach(o=>{o.m=0});
    }
    function rdm(num) {
       return  Math.floor(Math.random() * num);
    }
    function dG() {
        for (var i = 0; i < d.length; i++) {
            ctx.moveTo(c.r, c.r + i * c.d);
            ctx.lineTo(d[0].length*c.d-c.r, c.r + i * c.d);
        }
        for (var i = 0; i < d[0].length; i++) {
            ctx.moveTo(c.r + i * c.d, c.r);
            if( i !=0 && i != 8 ){
                ctx.lineTo(c.r + i * c.d,5*c.d-c.r);
                ctx.moveTo(c.r + i * c.d,6*c.d-c.r);
            }
            ctx.lineTo(c.r + i * c.d, d.length*c.d-c.r);
        }

        ctx.moveTo(4*c.d-c.r,c.r); ctx.lineTo(6*c.d-c.r,c.d*2+c.r);
        ctx.moveTo(6*c.d-c.r,c.r); ctx.lineTo(4*c.d-c.r,c.d*2+c.r);
        ctx.moveTo(4*c.d-c.r,9*c.d+c.r);ctx.lineTo(6*c.d-c.r,7*c.d+c.r);
        ctx.moveTo(6*c.d-c.r,9*c.d+c.r);ctx.lineTo(4*c.d-c.r,7*c.d+c.r);
        fd.forEach(o=>o.forEach(p=>{
            if(p!=null&& (p.n === "炮"||p.n === "兵" || p.n === "卒")){
                dx(p.x,p.y);
            }
        }))
        ctx.lineWidth = 1/5*c.r;
        ctx.strokeStyle = "#000";
        ctx.stroke();

        ctx.save();
        ctx.translate(9/2*c.d,10/2*c.d);
        ctx.rotate(0.5*Math.PI);
        ctx.font = c.r+"px Arial";
        ctx.fillStyle = 'black';
        ctx.fillText("楚", -0.25*c.d, +c.d);
        ctx.fillText("河", -0.25*c.d, +2*c.d);
        ctx.rotate(1*Math.PI);
        ctx.fillText("汉", -0.25*c.d, +c.d);
        ctx.fillText("界", -0.25*c.d, +2*c.d);
        ctx.rotate(1.5*Math.PI);
        ctx.restore();

    }
    function dCh() {
        d.forEach(o=>  o.forEach(p=>dc(p)));
    }
    function dcp(arr) {
        let newArr = [];
        for (let i = 0; i < arr.length; i++) {
            if (Array.isArray(arr[i])) {
                newArr[i] = dcp(arr[i]);
            } else if (typeof arr[i] === 'object' && arr[i] !== null) {
                newArr[i] = Object.assign({}, arr[i]);
            } else {
                newArr[i] = arr[i];
            }
        }
        return newArr;
    }
    function j(n){
        c.r+=(c.r+n*25>0?n*25:0);dr();
    }
    function sq() {
        var msg={};
        msg.to =document.getElementById("olu").value;
        if(msg.to===""){
            alert("请选中对手")
            return;
        }
        msg.from = sid;
        msg.type="1";
        ws.send(JSON.stringify(msg));
    }
    class C {
        constructor(x,y,n,t=1,s = 1,m = 1,an) {
            this.x = x;
            this.y = y;
            this.n = n;
            this.t = t;
            this.s = s;
            this.m = m;
            this.an = an?an:(n+"");
        }
    }
</script>
</body>
</html>
